package com.aierkeji.call.cms.service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.transaction.Transactional;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import com.aierkeji.call.cms.contants.Contants;
import com.aierkeji.call.cms.dao.jpa.AkjCallRoleDao;
import com.aierkeji.call.cms.dao.jpa.AkjCallUserDao;
import com.aierkeji.call.cms.entity.AkjCallRole;
import com.aierkeji.call.cms.entity.AkjCallUser;
import com.aierkeji.call.cms.entity.snap.AkjCallUserSnap;
import com.aierkeji.call.cms.entity.vo.AkjCallUserVo;
import com.aierkeji.call.cms.entity.vo.SearchOptionsVo;
import com.aierkeji.call.cms.exception.BatchException;
import com.aierkeji.call.cms.util.AppConfig;
import com.aierkeji.call.cms.util.CsvUtils;
import com.aierkeji.call.cms.util.DateTimeUtils;
import com.aierkeji.call.cms.util.ResultMapHelper;
import com.aierkeji.call.cms.util.StringUtils;
import com.aierkeji.call.cms.util.ValidataUtil;

@Service
public class AkjCallUserService {
	private final Logger log = LogManager.getLogger(getClass());

	@Autowired
	private AkjCallUserDao akjCallUserDao;

	@Autowired
	private AkjCallRoleDao akjCallRoleDao;

	public List<SearchOptionsVo> findCanAssigneUser(Map<String, Object> map) {
		// TODO Auto-generated method stub
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
		List<SearchOptionsVo> assigneTos = new ArrayList<SearchOptionsVo>();
		if (akjCallUser.checkRole(Contants.ROLE_ID_MANAGER) || akjCallUser.checkRole(Contants.ROLE_ID_ADMIN)) {
			assigneTos = akjCallUserDao.findCanAssigneUser(akjCallUser.getId());
		}else if(akjCallUser.checkRole(Contants.ROLE_ID_STATISTICIAN)) {
			assigneTos = akjCallUserDao.findCanAssigneUser(akjCallUser.getLeaderId());
		}
		return assigneTos;
	}

	String[] downLoadTempleteArr = { "手机号码", "密码", "姓名" };

	public Page<AkjCallUserVo> list(int pageNo, Map<String, Object> map,boolean isManager) {
		// TODO Auto-generated method stub
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
		String pageSize = (String) map.get("pageSize");
		Long leaderId = null;
		if (akjCallUser.checkRole(Contants.ROLE_ID_MANAGER)||
				(isManager&&akjCallUser.checkRole(Contants.ROLE_ID_ADMIN))) {
			leaderId = akjCallUser.getId();
			
		}else if(isManager&&akjCallUser.checkRole(Contants.ROLE_ID_ACCESS)) {
//			leaderId = akjCallUser.getId();
			map.put("createdBy", akjCallUser.getId());
		}else if(!isManager&&akjCallUser.checkRole(Contants.ROLE_ID_ADMIN)){
			map.put("admin_id", akjCallUser.getId());
		}
		Page<AkjCallUserVo> page = akjCallUserDao.getUserList(leaderId, map, pageNo,
				StringUtils.converStringToNumber(pageSize, Contants.PAGE_SIZE));
		List<AkjCallUserVo> list = page.getContent();
		if (!CollectionUtils.isEmpty(list)) {
			for (AkjCallUserVo vo : list) {
				List<String> rolesNames = this.akjCallUserDao.findRoleName(vo.getId());
				vo.setRolesNames(rolesNames);
			}
		}
		return page;
	}

	@Transactional
	public Map<String, Object> resetPassword(Map<String, Object> map) {
		// TODO Auto-generated method stub
		String password = (String) map.get("password");
		String rePassword = (String) map.get("rePassword");
		Integer id = (Integer) map.get("id");
		if (StringUtils.checkAnyNull(password, rePassword)) {
			return ResultMapHelper.nullParamsResult();
		}
		if (id == null || id <= 0) {
			return ResultMapHelper.nullParamsResult();

		}
		if (!password.equals(rePassword)) {
			return ResultMapHelper.failure("两次输入密码不一致!");
		}
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
		int count = akjCallUserDao.resetPassword(1L * id, akjCallUser.checkRole(Contants.ROLE_ID_ACCESS)?Contants.ADMINID:akjCallUser.getId(),
				DigestUtils.md5DigestAsHex(password.getBytes()), DateTimeUtils.getCurrentTime());
		if (count > 0) {
			return ResultMapHelper.success();
		}
		return ResultMapHelper.failure("重置失败！");
	}

	@Transactional
	public Map<String, Object> delete(Integer id) {
		// TODO Auto-generated method stub
		if (id == null || id <= 0) {
			return ResultMapHelper.nullParamsResult();
		}
		Optional<AkjCallUser> options = akjCallUserDao.findById(id * 1L);
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
		if (options.isPresent()) {
			AkjCallUser updateUser = options.get();
			if ((updateUser.getLeaderId() != null && akjCallUser.getId().compareTo(updateUser.getLeaderId()) == 0)
					||(akjCallUser.checkRole(Contants.ROLE_ID_ACCESS)&&akjCallUser.getId().compareTo(updateUser.getCreatedBy())==0)) {
			String accountDeleteRemark = "|deleted-mark|" + LocalDateTime.now().getSecond();
				updateUser.setDelete(true);
				updateUser.setUpdatedBy(AkjCallUserSnap.build(akjCallUser));
				updateUser.setUpdatedAt(DateTimeUtils.getCurrentTime());
				updateUser.setAccount(updateUser.getAccount() +accountDeleteRemark);
				//如果是停用企业管理员，则停用下面所有的坐席
				if(updateUser.checkRole(Contants.ROLE_ID_MANAGER)) {
					if(updateUser.getEnterprise()!=null) {
						updateUser.getEnterprise().setDelete(true);
					}
					int count = this.akjCallUserDao.deleteSubUser(true, updateUser.getId(),akjCallUser.getId(), updateUser.getUpdatedAt(), accountDeleteRemark);
					log.info("delete manage sub user count :{},leaderid:{}",count,updateUser.getId());
				}
				this.akjCallUserDao.save(updateUser);
			} else {

				return ResultMapHelper.failure("没有权限停止该用户");
			}
		} else {
			return ResultMapHelper.failure("没有找到用户!");
		}

		return ResultMapHelper.success("停用成功");
	}

	@Transactional
	public Map<String, Object> edit(Map<String, Object> map) {
		// TODO Auto-generated method stub
		Integer id = (Integer) map.get("id");
		String name = (String) map.get("name");
		if (id == null || id <= 0 || StringUtils.checkAnyNull(name)) {
			return ResultMapHelper.nullParamsResult();
		}
		Optional<AkjCallUser> options = akjCallUserDao.findById(id * 1L);
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
		if (options.isPresent()) {
			AkjCallUser updateUser = options.get();
			if ((updateUser.getLeaderId() != null && akjCallUser.getId().compareTo(updateUser.getLeaderId()) == 0)// 修改子级
					|| (Long.compare(updateUser.getId(), akjCallUser.getId()) == 0)// 修改自己
					||(akjCallUser.checkRole(Contants.ROLE_ID_ACCESS)&&updateUser.getCreatedBy().compareTo(akjCallUser.getId())==0))//access 修改企业管理员
			 {
				if (updateUser.getName().equals(name)) {
					return ResultMapHelper.success();
				}
				updateUser.setUpdatedBy(AkjCallUserSnap.build(akjCallUser));
				updateUser.setUpdatedAt(DateTimeUtils.getCurrentTime());
				updateUser.setName(name);
				this.akjCallUserDao.save(updateUser);
			} else {
				return ResultMapHelper.failure("没有权限修改该用户");
			}
		} else {
			return ResultMapHelper.failure("没有找到用户!");
		}
		return ResultMapHelper.success();
	}

	@Transactional
	public Map<String, Object> editPassword(Map<String, Object> map) {
		String password = (String) map.get("password");
		String rePassword = (String) map.get("rePassword");
		String oldPassword = (String) map.get("oldPassword");
		if (StringUtils.checkAnyNull(password, rePassword, oldPassword)) {
			return ResultMapHelper.nullParamsResult();
		}
		if (!password.equals(rePassword)) {
			return ResultMapHelper.failure("两次输入密码不一致!");
		}
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
		if (!akjCallUser.getPwd().equals(DigestUtils.md5DigestAsHex(oldPassword.getBytes()))) {
			return ResultMapHelper.failure("旧密码错误!");
		}
		akjCallUser.setPwd(DigestUtils.md5DigestAsHex(password.getBytes()));
		akjCallUser.setUpdatedBy(AkjCallUserSnap.build(akjCallUser));
		akjCallUser.setUpdatedAt(DateTimeUtils.getCurrentTime());
		this.akjCallUserDao.save(akjCallUser);
		return ResultMapHelper.success();
	}

	public Map<String, Object> getAllRoles() {
		// TODO Auto-generated method stub
		List<AkjCallRole> list = akjCallRoleDao.findAll();
		if (!Boolean.valueOf(AppConfig.getProperty("showAllRole", "false"))) {
			Subject subject = SecurityUtils.getSubject();
			AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");
			if (akjCallUser.checkRole(Contants.ROLE_ID_ADMIN)||akjCallUser.checkRole(Contants.ROLE_ID_ACCESS)) {
				list = list.stream()
						.filter(k -> StringUtils.equalsAny(k.getCode(), new String[] { Contants.ROLE_ID_MANAGER }))
						.collect(Collectors.toList());
			} else {
				list = list.stream()
						.filter(k -> StringUtils.equalsAny(k.getCode(),
								new String[] { Contants.ROLE_ID_SALES, Contants.ROLE_ID_STATISTICIAN }))
						.collect(Collectors.toList());
			}
		}
		return ResultMapHelper.success(list);
	}

	public Map<String, Object> addUser(Map<String, Object> map) {
		// TODO Auto-generated method stub
		String name = (String) map.get("name");
		String password = (String) map.get("password");
		String rePassword = (String) map.get("rePassword");
		String phone = (String) map.get("phone");
		List<String> roles = (List<String>) map.get("roles");
		if (StringUtils.checkAnyNull(name, password, rePassword, phone)) {
			return ResultMapHelper.nullParamsResult();
		}

		if (CollectionUtils.isEmpty(roles)) {
			return ResultMapHelper.nullParamsResult();
		}
		if (!password.equals(rePassword)) {
			return ResultMapHelper.failure("密码不一致，请重新输入！");
		}
		if (!ValidataUtil.isMobilePhone(phone)) {
			return ResultMapHelper.failure("手机号码格式不正确");
		}
		List<AkjCallRole> callRoles = roles.stream().map((k) -> {
			AkjCallRole akjCallRole = new AkjCallRole();
			akjCallRole.setId(Long.parseLong(k));
			return akjCallRole;
		}).collect(Collectors.toList());
		AkjCallUser akjCallUser = addUser(name, password, rePassword, phone, callRoles);
		try {

			this.akjCallUserDao.save(akjCallUser);
			return ResultMapHelper.success(akjCallUser);
		} catch (org.springframework.dao.DataIntegrityViolationException e) {
			// TODO: handle exception
			log.error("", e);
			if (org.hibernate.exception.ConstraintViolationException.class.getName()
					.equals(e.getCause().getClass().getName())) {
				return ResultMapHelper.failure("增加用户失败！手机号码重复");
			}
		} catch (Exception e) {
			// TODO: handle exception
			log.error("", e);

		}

		return ResultMapHelper.failure("增加用户失败！");
	}

	@Transactional(rollbackOn=BatchException.class)
	public Map<String, Object> batchAddUser(MultipartFile file) throws BatchException {
		// TODO Auto-generated method stub
		// TODO Auto-generated method stub
		if (file == null) {
			return ResultMapHelper.nullParamsResult();
		}
		InputStream is;
		try {
			is = file.getInputStream();

			BufferedReader bf = new BufferedReader(new InputStreamReader(is, "GBK"));
			String line = "";
			List<String> list = new ArrayList<>();
			while ((line = bf.readLine()) != null) {
				if (!StringUtils.isEmpty(line)) {
					list.add(line.trim());

				}
			}
			bf.close();
			List<AkjCallUser> saveList = new ArrayList<>();
			List<AkjCallRole> roles = akjCallRoleDao.findByCode(Contants.ROLE_ID_SALES);

			log.info("batch save user size:{}", list.size());
			for (int index = 0; index < list.size(); index++) {
				if (index == 0) {
					continue;
				}
				line = list.get(index);

				String[] columnArr = line.split(CsvUtils.getCsvColumnSeparator(), downLoadTempleteArr.length);
				if (columnArr.length != downLoadTempleteArr.length) {
					list = null;
					saveList = null;
					return ResultMapHelper.failure("CSV格式错误");
				}
				String phone = columnArr[0];
				String password = columnArr[1];
				String name = columnArr[2];
				if (StringUtils.checkAnyNull(phone, password, name) || !ValidataUtil.isMobilePhone(phone)) {
					return ResultMapHelper.failure("第" + (index + 1) + "行数据格式有误");
				}
				saveList.add(addUser(name, password, password, phone, roles));
			}
			if (!CollectionUtils.isEmpty(saveList)) {
				saveList.forEach(k -> {
					this.akjCallUserDao.save(k);
				});
			}
			return ResultMapHelper.success();
		} catch (org.springframework.dao.DataIntegrityViolationException e) {
			// TODO: handle exception
			log.error("", e);
			if (org.hibernate.exception.ConstraintViolationException.class.getName()
					.equals(e.getCause().getClass().getName())) {
				throw new BatchException("批量增加坐席失败！手机号码重复");
			}
		} catch (Exception e) {
			// TODO: handle exception
			log.error("", e);
		}
		return ResultMapHelper.failure("批量增加坐席失败!");

	}

	public AkjCallUser addUser(String name, String password, String rePassword, String phone,
			List<AkjCallRole> callRoles) {
		Subject subject = SecurityUtils.getSubject();
		AkjCallUser akjCallUser = (AkjCallUser) subject.getSession().getAttribute("loginUser");

		AkjCallUser saveUser = new AkjCallUser();
		saveUser.setAccount(phone);
		saveUser.setName(name);
		saveUser.setPwd(DigestUtils.md5DigestAsHex(password.getBytes()));
		saveUser.setCreatedAt(DateTimeUtils.getCurrentTime());
		if(akjCallUser.checkRole(Contants.ROLE_ID_ACCESS)) {
			saveUser.setLeaderId(Contants.ADMINID);//admin
		}else {
			saveUser.setLeaderId(akjCallUser.getId());
		}
		saveUser.setCreatedBy(akjCallUser.getId());
		if(akjCallUser.getEnterprise()!=null) {
			saveUser.setApprovedAt(saveUser.getCreatedAt());
			saveUser.setEnterprise(akjCallUser.getEnterprise());
		}

		saveUser.setRoles(callRoles);

		return saveUser;
	}

	public Map<String, Object> downloadAddUserTemplete() {
		// TODO Auto-generated method stub
		String str = CsvUtils.doExport(false, downLoadTempleteArr);
		return ResultMapHelper.success(str);
	}

}
